Skip to content

feat(bills): wire web bills page to NGN rails and extract shared mobile BillFlow - #1145

Open
Meet-hybrid wants to merge 7 commits into
Miracle656:mainfrom
Meet-hybrid:feat/bills-flow-and-ngn-rails-1131-1132
Open

Meet-hybrid wants to merge 7 commits into
Miracle656:mainfrom
Meet-hybrid:feat/bills-flow-and-ngn-rails-1131-1132

Conversation

@Meet-hybrid

Copy link
Copy Markdown
Contributor

Overview

This PR addresses two related issues in the Nigerian bills and NGN rails layer across the web and mobile wallets:

  1. Web wallet bills page & NGN rails documentation (#1131): frontend/wallet/app/bills/page.tsx previously stated that the naira conversion and bill rails were not built and disabled every service tile, even though /ngn/bills shipped on Linq and airtime is live. We added the /ngn/bills client methods (payBill, getBillStatus, BillCategory, BillOrder, BillStatus) to frontend/wallet/lib/ngn.ts, updated frontend/wallet/app/bills/page.tsx so live services (Airtime and Transfer → /cashout) are active while unshipped categories remain honestly marked Soon (with zero invented balances or fake history), and updated the remaining eBills-blocker references in docs/NGN_RAILS.md.
  2. Shared mobile bill flow (#1132): frontend/mobile/app/airtime.tsx previously bundled the entire 5-step bill payment state machine (form → confirm → paying → done / failed) alongside airtime-specific phone and prefix logic. We extracted the shared bill payment machinery into frontend/mobile/lib/billFlow.ts and frontend/mobile/components/BillFlow.tsx behind a documented per-category seam (BillCategoryConfig), and refactored frontend/mobile/app/airtime.tsx to be the first consumer of BillFlow.

Related Issues


Changes

Issue 1 — Web wallet bills page & docs/NGN_RAILS.md (#1131)

  • frontend/wallet/lib/ngn.ts:
    • Added BillCategory, BillOrder, BillStatus, payBill (POST /ngn/bills), and getBillStatus (GET /ngn/bills/:orderId?customerRef=...) sharing the existing call<T> client (x-network: mainnet header, transient retry budget, and provider-name scrubbing).
  • frontend/wallet/app/bills/page.tsx:
    • Updated the file docblock to describe what is true today on the Linq /ngn/bills rail.
    • Replaced the stale "Not live yet — The rails are chosen. The paperwork is not done" card with the live Airtime top-up flow backed by @/lib/ngn (mainnet gate, one-time NIN KYC check and /verify?returnTo=/bills handoff, prefix-based network detection with manual override, per-coin rate quote, order reservation via payBill, /send deposit handoff, and getBillStatus polling).
    • Marked Airtime and Transfer (/cashout) as Live in the Pay for grid while keeping unshipped categories marked Soon, with no invented balances or fake purchase history.
  • docs/NGN_RAILS.md:
    • Updated the Decided sequencing, First blocker, and Open items sections to reflect that /ngn/bills shipped on Linq (wraith/src/linq/bills.ts) and superseded the eBills float/reseller-role blocker.
  • frontend/wallet/lib/__tests__/ngn.test.ts:
    • Added unit tests for payBill and getBillStatus.

Issue 2 — Shared mobile bill flow & per-category seam (#1132)

  • frontend/mobile/lib/billFlow.ts:
    • Defined and documented the per-category seam (BillCategoryConfig, BillCategoryCopy, BillSummaryRow, BillStep, BillRateState).
    • Extracted shared helpers (parseBillAmountNgn, computeBillCryptoCost, lockBillAmountStableCoin, canContinueBillForm, classifyBillPollStatus, and executeBillPayment enforcing reserve-first via payBill and spend-second via spendAsset using the order's locked amount).
  • frontend/mobile/components/BillFlow.tsx:
    • Extracted the shared 5-step React Native bill payment flow (form → confirm → paying → done / failed), including mainnet gating, customerRef and classic G… refundAddress resolution, per-coin rate loading, NIN KYC check and /verify bounce, previewSpendFee on the confirm step before the passkey prompt, order reservation + spend execution, and getBillStatus polling with silent transient poll error handling.
  • frontend/mobile/app/airtime.tsx:
    • Refactored AirtimeScreen onto <BillFlow>, keeping PREFIXES, NETWORKS, detectNetwork, isValidNigerianPhone, buildAirtimeCategoryConfig, the network selector chips, and the phone number input + contact picker on the airtime side of the seam.
  • frontend/mobile/lib/__tests__/billFlow.test.ts:
    • Added unit tests covering the shared bill flow invariants (reserve-before-spend ordering, no spend on reservation failure, locked 7-decimal amount, poll status classification), airtime prefix/phone helpers, and a second bill category (electricity) plugged into the shared seam without duplicating flow logic.

Verification Results

  • Git diff and static inspection — passed
  • CI — pending

@vercel

vercel Bot commented Oct 20, 2026

Copy link
Copy Markdown

@Meet-hybrid is attempting to deploy a commit to the miracle656's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Oct 20, 2026

Copy link
Copy Markdown

@Meet-hybrid Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Meet-hybrid and others added 3 commits October 22, 2026 01:05
The two web-editor merges of main kept both sides of each conflict instead
of choosing between them, leaving bills/page.tsx, billFlow.ts and its test
syntactically broken. Redo the resolution:

- Web (Miracle656#1131): keep main's bills page and naira client, which already ship
  the live airtime flow with bounded polling and passkey-cancel handling,
  and port this PR's "Pay for" grid (Airtime and Transfer live, the rest
  marked Soon) into it. Keep this PR's payBill/getBillStatus tests.
- Mobile (Miracle656#1132): keep the shared BillFlow refactor and fold in main's
  changes: the 'unconfirmed' step, 'cancel' as a failed status, and the
  passkey-cancel handling (now in components/BillFlow.tsx, since airtime.tsx
  delegates to it).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Meet-hybrid

Copy link
Copy Markdown
Contributor Author

Merge-conflict fix pushed (efbc953): the earlier web-editor merges had kept both sides of the conflicts. Wallet typecheck/build and Playwright E2E now pass. The remaining Mobile and Maestro failures are the same 7 type errors currently failing on main (app/(tabs)/agent.tsx, app/dapp.tsx, ServicesDrawer.tsx, SilverBalanceCard.tsx, lib/__tests__/about.test.ts), none in files this PR touches. Vercel needs maintainer authorization.

@gitguardian

gitguardian Bot commented Oct 24, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 1 secret following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

Since your pull request originates from a forked repository, GitGuardian is not able to associate the secrets uncovered with secret incidents on your GitGuardian dashboard.
Skipping this check run and merging your pull request will create secret incidents on your GitGuardian dashboard.

🔎 Detected hardcoded secret in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
38349992 Triggered Generic High Entropy Secret 93aed41 sdk/src/tests/allowance.test.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secret safely. Learn here the best practices.
  3. Revoke and rotate this secret.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

One bill flow, not five copies of airtime.tsx The web wallet's bills page says nothing is live. It is now wrong.

1 participant